import { Node, Edge } from '@antv/x6';
import type { ProcessProps } from './index';
import { BpmnShapeTags } from '../elements'
import xmlFormat from 'xml-formatter';

const convertGraphData2Xml = (processProps:ProcessProps, nodes:Node[], edges:Edge[]):string=>{
  console.log(processProps,nodes,edges);

  const bpmnDoc = new Document();
  // 根元素<definitions/>
  const _definitions = bpmnDoc.appendChild(bpmnDoc.createElement('definitions'));
  _definitions.setAttribute("xmlns","http://www.omg.org/spec/BPMN/20100524/MODEL");
  _definitions.setAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
  _definitions.setAttribute("xmlns:xsd","http://www.w3.org/2001/XMLSchema");
  _definitions.setAttribute("xmlns:flowable","http://flowable.org/bpmn");
  _definitions.setAttribute("xmlns:bpmndi","http://www.omg.org/spec/BPMN/20100524/DI");
  _definitions.setAttribute("xmlns:omgdc","http://www.omg.org/spec/DD/20100524/DC");
  _definitions.setAttribute("xmlns:omgdi","http://www.omg.org/spec/DD/20100524/DI");
  _definitions.setAttribute("typeLanguage","http://www.w3.org/2001/XMLSchema");
  _definitions.setAttribute("expressionLanguage","http://www.w3.org/1999/XPath");
  _definitions.setAttribute("targetNamespace","http://www.flowable.org/processdef");

  // 流程元素<process/>
  const _process = _definitions.appendChild(bpmnDoc.createElement('process'));
  _process.setAttribute('id',processProps.id);
  _process.setAttribute('name',processProps.name||"");
  _process.setAttribute('isExecutable',processProps.isExecutable===false?'false':'true');
  // 流程启动者
  _process.setAttribute('flowable:candidateStarterUsers',processProps.candidateStarterUsers);
  // 流程启动者组
  _process.setAttribute('flowable:candidateStarterGroups',processProps.candidateStarterGroups);
  // 描述文档元素<documentation/>
  processProps.documentation && _process.appendChild(bpmnDoc.createElement('documentation')).append(processProps.documentation);

  // 画板元素<bpmndi:BPMNDiagram/>
  const _bpmndiagram = _definitions.appendChild(bpmnDoc.createElement('bpmndi:BPMNDiagram'));
  _bpmndiagram.setAttribute('id',`BPMNDiagram_${processProps.id}`);

  // 平面元素<bpmndi:BPMNPlane/>
  const _bpmnplane = _bpmndiagram.appendChild(bpmnDoc.createElement('bpmndi:BPMNPlane'));
  _bpmnplane.setAttribute('bpmnElement',processProps.id);
  _bpmnplane.setAttribute('id',`BPMNPlane_${processProps.id}`);

  // 节点元素
  for(let node of nodes){
    const _bpmnNode = _process.appendChild(bpmnDoc.createElement(BpmnShapeTags[node.shape]));
    _bpmnNode.setAttribute('id',node.id);
    _bpmnNode.setAttribute('name',(node as any).label as string||"");
    if(node.data){
      // 描述文档元素<documentation/>
      node.data.documentation && _bpmnNode.appendChild(bpmnDoc.createElement('documentation')).append(node.data.documentation as string);
      // 发起人
      node.data.initiator && _bpmnNode.setAttribute("flowable:initiator",node.data.initiator);
      // 是否异步
      node.data.async==='true' && _bpmnNode.setAttribute("flowable:async",'true');
      // 是否独占
      node.data.exclusive==='true' && _bpmnNode.setAttribute("flowable:exclusive",'true');
      // 是否补偿
      node.data.isForCompensation==='true' && _bpmnNode.setAttribute("isForCompensation",'true');
      // 分类
      node.data.category && _bpmnNode.setAttribute("flowable:category",node.data.category);
      // 到期时间
      node.data.dueDate && _bpmnNode.setAttribute("flowable:dueDate",node.data.dueDate);
      // 优先级
      node.data.priority && _bpmnNode.setAttribute("flowable:priority",node.data.priority);
      // 跳过表达式
      node.data.skipExpression && _bpmnNode.setAttribute("flowable:skipExpression",node.data.skipExpression);
      // 处理用户
      node.data.assignee && _bpmnNode.setAttribute("flowable:assignee",node.data.assignee);
      // 候选用户
      node.data.candidateUsers && _bpmnNode.setAttribute("flowable:candidateUsers",node.data.candidateUsers);
      // 候选用户组
      node.data.candidateGroups && _bpmnNode.setAttribute("flowable:candidateGroups",node.data.candidateGroups);
      // 服务任务Java类
      node.data.class && _bpmnNode.setAttribute("flowable:class",node.data.class);
      // 服务任务结果变量名
      node.data.resultVariableName && _bpmnNode.setAttribute("flowable:resultVariableName",node.data.resultVariableName);
      // 服务任务可触发的
      node.data.triggerable==='true' && _bpmnNode.setAttribute("flowable:triggerable",'true');
      // 服务任务结果变量局部有效
      node.data.useLocalScopeForResultVariable==='true' && _bpmnNode.setAttribute("flowable:useLocalScopeForResultVariable",'true');
      // 服务任务结果变量瞬态存储
      node.data.storeResultVariableAsTransient==='true' && _bpmnNode.setAttribute("flowable:storeResultVariableAsTransient",'true');
      // 多实例元素<multiInstanceLoopCharacteristics/>
      if(['true','false'].includes(node.data.multi_isSequential)){
        const _multiInstance = _bpmnNode.appendChild(bpmnDoc.createElement('multiInstanceLoopCharacteristics'));
        _multiInstance.setAttribute("isSequential",node.data.multi_isSequential);
        // 集合
        node.data.multi_collection && _multiInstance.setAttribute("flowable:collection",node.data.multi_collection);
        // 元素变量
        node.data.multi_elementVariable && _multiInstance.setAttribute("flowable:elementVariable",node.data.multi_elementVariable);
        // 基数<loopCardinality/>
        node.data.multi_loopCardinality && _multiInstance.appendChild(bpmnDoc.createElement('loopCardinality')).append(node.data.multi_loopCardinality);
        // 完成条件<completionCondition/>
        node.data.multi_completionCondition && _multiInstance.appendChild(bpmnDoc.createElement('completionCondition')).append(node.data.multi_completionCondition);
      }
      // 扩展元素<extensionElements/>
      const _extensionElements = _bpmnNode.appendChild(bpmnDoc.createElement('extensionElements'));
      // 动态表单属性元素<flowable:formProperty/>
      if(node.data.formProperty){
        node.data.formProperty.forEach((item:any)=>{
          const _formProperty = _extensionElements.appendChild(bpmnDoc.createElement('flowable:formProperty'));
          _formProperty.setAttribute("id",item.id || '');
          _formProperty.setAttribute("name",item.name || '');
          _formProperty.setAttribute("type",item.type || 'string');
          _formProperty.setAttribute("expression",item.expression || '');
          _formProperty.setAttribute("variable",item.variable || '');
          _formProperty.setAttribute("default",item.default || '');
          item.readable==='false' && _formProperty.setAttribute("readable",'false');
          item.writable==='false' && _formProperty.setAttribute("writable",'false');
          item.required==='true' && _formProperty.setAttribute("required",'true');
        });
      }
    }

    // 节点图形元素<bpmndi:BPMNShape/>
    const _bpmnShape = _bpmnplane.appendChild(bpmnDoc.createElement('bpmndi:BPMNShape'));
    _bpmnShape.setAttribute("bpmnElement", node.id);
    _bpmnShape.setAttribute("id", `BPMNShape_${node.id as string}`);
    const _bounds = _bpmnShape.appendChild(bpmnDoc.createElement('omgdc:Bounds'));
    _bounds.setAttribute("width",''+node.getSize().width);
    _bounds.setAttribute("height",''+node.getSize().height);
    _bounds.setAttribute("x",''+node.getPosition().x);
    _bounds.setAttribute("y",''+node.getPosition().y);
  }

  // 流程路径元素
  for(let edge of edges){
    const _bpmnFlow = _process.appendChild(bpmnDoc.createElement(BpmnShapeTags[edge.shape]));
    _bpmnFlow.setAttribute('id',edge.id as string);
    _bpmnFlow.setAttribute('name',(edge as any).label as string || '');
    _bpmnFlow.setAttribute('sourceRef',(edge.source as any).cell);
    _bpmnFlow.setAttribute('targetRef',(edge.target as any).cell);
    if(edge.data){
      // 描述文档元素<documentation/>
      edge.data.documentation && _bpmnFlow.appendChild(bpmnDoc.createElement('documentation')).append(edge.data.documentation as string);
      // 跳过表达式
      edge.data.skipExpression && _bpmnFlow.setAttribute("skipExpression",edge.data.skipExpression);
      // 流转条件表达式元素<conditionExpression/>
      if(edge.data.conditionExpression){
        const _conditionExpression = _bpmnFlow.appendChild(bpmnDoc.createElement('conditionExpression'));
        _conditionExpression.setAttribute("xsi:type","tFormalExpression");
        _conditionExpression.append('<![CDATA['+edge.data.conditionExpression+']]>');
      }
    }

    // 路径图形元素
    const _bpmnEdge = _bpmnplane.appendChild(bpmnDoc.createElement('bpmndi:BPMNEdge'));
    _bpmnEdge.setAttribute("bpmnElement", edge.id);
    _bpmnEdge.setAttribute("id", `BPMNShape_${edge.id as string}`);
    edge.getVertices().forEach((vertice)=>{
      const _waypoint = _bpmnEdge.appendChild(bpmnDoc.createElement('omgdi:waypoint'));
      _waypoint.setAttribute("x",vertice.x);
      _waypoint.setAttribute("y",vertice.y);
    })

  }

  let bpmnXml = xmlFormat('<?xml version="1.0" encoding="UTF-8"?>'+bpmnDoc.documentElement.outerHTML,{indentation: '  '});
  bpmnXml = bpmnXml.replaceAll('&lt;','<').replaceAll('&gt;','>');
  console.log('convertXml bpmnXml=',bpmnXml);
  return bpmnXml;
}

export default convertGraphData2Xml;